package com.common.web.html;

import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.NullArgumentException;

/**
 * @description HTML标签
 * @author lj
 * @createTime 2016年9月11日 下午5:18:42
 */
public class HTMLTag {

    private String name;

    private List<Attribute> attributes;

    private String textNode;

    private List<HTMLTag> contentNodes;

    private List<Style> styles;

    /**
     * 
     * @description HTML标签属性，但请不要在属性中添加样式属性（style）
     * @author lj
     * @createTime 2016年9月24日 下午1:16:28
     */
    private static final class Attribute {
        String name; // 属性名
        String value; // 属性值

        public Attribute(String name, String value) {
            this.name = name;
            this.value = value;
        }
    }

    /**
     * 
     * @description HTML样式
     * @author lj
     * @createTime 2016年9月24日 下午1:16:55
     */
    private static final class Style {
        String attr;
        String value;

        public Style(String attr, String value) {
            this.attr = attr;
            this.value = value;
        }
    }

    public HTMLTag(String name) {
        if (name == null || "".equals(name.trim())) {
            throw new NullArgumentException("name");
        }
        this.name = name;
        this.attributes = new LinkedList<Attribute>();
        this.contentNodes = new LinkedList<HTMLTag>();
        this.styles = new LinkedList<Style>();
    }

    /**
     * 
     * @description 添加样式
     * @author lj
     * @date 2016年9月24日 下午1:16:09
     * @param attr
     * @param value
     * @return
     */
    public HTMLTag addStyle(String attr, String value) {
        for (Style style : styles) {
            if (style.attr.equals(attr)) {
                style.value = value;
                return this;
            }
        }
        styles.add(new Style(attr, value));
        return this;
    }

    /**
     * 
     * @description 添加属性，但不允许添加style
     * @author lj
     * @date 2016年9月24日 下午12:52:47
     * @param attrName
     * @param attrValue
     * @return
     */
    public HTMLTag addAttribute(String attrName, String attrValue) {
        if ("style".equals(attrName)) {
            throw new IllegalArgumentException("if you want to add styles,please use API: addStyle method");
        }
        for (Attribute attr : attributes) {
            if (attr.name.equals(attrName)) {
                attr.value = attrValue;
                return this;
            }
        }
        attributes.add(new Attribute(attrName, attrValue));
        return this;
    }

    /**
     * 
     * @description 移除属性
     * @author lj
     * @date 2016年9月24日 下午12:57:38
     * @param attrName
     * @return
     */
    public HTMLTag removeAttribute(String attrName) {
        for (Attribute attr : attributes) {
            if (attr.name.equals(attrName)) {
                attributes.remove(attr);
                return this;
            }
        }
        return this;
    }

    /**
     * 
     * @description 删除样式
     * @author lj
     * @date 2016年9月24日 下午1:02:49
     * @param attr
     * @return
     */
    public HTMLTag removeStyle(String attr) {
        for (Style style : styles) {
            if (style.attr.equals(attr)) {
                styles.remove(style);
                return this;
            }
        }
        return this;
    }

    /**
     * @param {@link #textNode}
     */
    public HTMLTag setTextNode(String textNode) {
        this.textNode = textNode;
        return this;
    }

    /**
     * 
     * @description 删除文本节点
     * @author lj
     * @date 2016年9月11日 下午7:06:25
     * @return
     */
    public HTMLTag removeTextNode() {
        textNode = "";
        return this;
    }

    /**
     * @return {@link #textNode}
     */
    public String getTextNode() {
        return textNode;
    }

    /**
     * 
     * @description 添加子节点
     * @author lj
     * @date 2016年9月24日 下午12:57:55
     * @param tag
     * @return
     */
    public HTMLTag addContentNode(HTMLTag tag) {
        contentNodes.add(tag);
        return this;
    }

    /**
     * @return {@link #contentNodes}
     */
    public List<HTMLTag> getContentNodes() {
        return contentNodes;
    }

    /**
     * 
     * @description 根据下标获取子节点
     * @author lj
     * @date 2016年9月24日 下午1:15:30
     * @param index
     * @return
     */
    public HTMLTag getContentNode(int index) {
        if (index >= contentNodes.size()) {
            throw new IllegalArgumentException("index");
        }
        return contentNodes.get(index);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(12);
        sb.append("<").append(name);
        for (Attribute attr : attributes) {
            sb.append(" ").append(attr.name).append("=\"").append(attr.value).append("\"");
        }
        if (styles.size() != 0) {
            sb.append(" style=\"");
            for (Style style : styles) {
                sb.append(style.attr).append(":").append(style.value).append(";");
            }
            sb.append("\"");
        }
        sb.append(">");
        if (textNode != null && !"".equals(textNode.trim())) {
            sb.append(textNode);
        }
        if (contentNodes != null) {
            for (HTMLTag tag : contentNodes) {
                sb.append(tag.toString());
            }
        }
        sb.append("</");
        sb.append(name);
        sb.append(">");
        return sb.toString();
    }

    /**
     * @description 删除所有子标签
     * @author lj
     * @date 2016年9月11日 下午10:40:26
     */
    public HTMLTag clearContentNodes() {
        contentNodes.clear();
        return this;
    }

    /**
     * 
     * @description 删除所有属性
     * @author lj
     * @date 2016年9月24日 下午1:00:18
     * @return
     */
    public HTMLTag clearAttributes() {
        attributes.clear();
        return this;
    }

    /**
     * 
     * @description 删除某个节点
     * @author lj
     * @date 2016年9月11日 下午10:46:27
     * @param index
     * @return
     */
    public HTMLTag removeContentNode(int index) {
        if (index >= contentNodes.size()) {
            throw new IllegalArgumentException("index");
        }
        contentNodes.remove(index);
        return this;
    }
}
